home *** CD-ROM | disk | FTP | other *** search
/ The Original Shareware 1.1 / The Original Shareware (WeMake CDs)(Volume 1.1)(CDs, Inc)(1993).iso / 32 / othello.zip / OTH42.BAS next >
BASIC Source File  |  1987-08-23  |  34KB  |  873 lines

  1. REM ** OTHELLO ** VER 4.2 ** DMK ** 08/23/87 **
  2. REM *************************************************************************
  3.     DEFINT A-Z: ON ERROR GOTO PROGRAM.ERROR
  4. REM *************************************************************************
  5. REM ** FUNCTIONS **
  6. DEF FNS$(A$)
  7.     STATIC A: FNS$="": IF A$="" THEN EXIT DEF
  8.     FOR A=LEN(A$) TO 1 STEP -1
  9.         IF INSTR(CHR$(0)+" ",MID$(A$,A,1))=0 THEN FNS$=MID$(A$,1,A): A=1
  10.     NEXT
  11. END DEF
  12. REM *************************************************************************
  13. REM ** INITIALIZE PROGRAM **
  14.     DIM BOARD(64,64),TOKEN$(2),PLAYER$(2),SCORE(2),CLF(6),CLB(6)
  15.     DIM DIR(7,1),BAD!(64,1),GP$(10),GP(10,1),CUR.BOARD(64,1),SIDE(8,1)
  16.     SCREEN 0,0,0: WIDTH 80: COLOR 7,0: CLS
  17.     PRINT "                                 ** OTHELLO **"
  18.     PRINT "                              THE GAME OF OTHELLO"
  19.     PRINT
  20.     PRINT "     WRITTEN AND COMPILED BY DAVID KEIL OF GREENVILLE, SC (803) 295-4971"
  21.     PRINT
  22.     PRINT "                                  VERSION 4.2"
  23.     LOCATE 12,15: PRINT "Would you like sound effects (Y or N)? ";
  24.     CALL SCREEN.INPUT((12),(POS(0)),1,"",SN$,"YN"): PRINT SN$;
  25.     LOCATE 14,15: PRINT "Do you have a color monitor (Y or N)? ";
  26.     CALL SCREEN.INPUT((14),(POS(0)),1,"",A$,"YN"): PRINT A$;
  27.     IF A$="Y" THEN RESTORE COLOR.DATA ELSE RESTORE MONO.DATA
  28.     FOR A=0 TO 6: READ CLF(A),CLB(A): NEXT
  29.     LOCATE 16,15: PRINT "Do you want to use joystick (Y or N)? ";
  30.     CALL SCREEN.INPUT((16),(POS(0)),1,"",JS$,"YN"): PRINT JS$;
  31.     IF JS$="Y" THEN
  32.         LOCATE 18,15: PRINT "Center joystick and push any key.";
  33.         WHILE INKEY$="": WEND: CALL MAKE.SOUND((3))
  34.         JS2=STICK(0): JS2=STICK(0): JS1=STICK(1)
  35.     END IF
  36.     RESTORE MOVE.DATA: FOR A=0 TO 7: READ DIR(A,0),DIR(A,1): NEXT
  37.     CALL MOUSE((-1),(0),(0),(0)): GOSUB PRINT.INSTR: GOSUB GET.SCORES
  38.     RANDOMIZE TIMER
  39. REM *************************************************************************
  40. START:
  41.     FOR A=1 TO 64: BOARD(A,0)=0: NEXT: MOVE=1
  42.     SCORE(1)=0: SCORE(2)=0: GOSUB DRAW.BOARD: GOSUB DISPLAY.SCORES
  43.     CALL PRINT.MSG(("How many players? "),(0))
  44.     CALL SCREEN.INPUT((25),(POS(0)),1,"",A$,"12"): PLAYERS=VAL(A$)
  45.     FOR A=1 TO PLAYERS
  46.         CALL PRINT.MSG(("Enter name player"+STR$(A)+": "),A)
  47. GET.NAME:
  48.         CALL SCREEN.INPUT((25),(POS(0)),10,PLAYER$(A),PLAYER$(A),"ABCDEFGHIJKLMNOPQRSTUVWXYZ. ")
  49.         PLAYER$(A)=FNS$(PLAYER$(A))
  50.         IF PLAYER$(A)="" THEN CALL MAKE.SOUND((4)): GOTO GET.NAME
  51.     NEXT: IF PLAYERS=1 THEN PLAYER$(2)="COMPUTER"
  52.     CALL PRINT.MSG("Enter pattern 1-          2-         (1 or 2)?",(0))
  53.     LOCATE 24,17: COLOR CLF(1),CLB(1): PRINT TOKEN$(1);
  54.     LOCATE 24,21: COLOR CLF(2),CLB(2): PRINT TOKEN$(2);
  55.     LOCATE 24,29: COLOR CLF(1),CLB(1): PRINT TOKEN$(1): LOCATE 24,33: PRINT TOKEN$(1);
  56.     LOCATE 25,17: COLOR CLF(2),CLB(2): PRINT TOKEN$(2);
  57.     LOCATE 25,21: COLOR CLF(1),CLB(1): PRINT TOKEN$(1);
  58.     LOCATE 25,29: COLOR CLF(2),CLB(2): PRINT TOKEN$(2);: LOCATE 25,33: PRINT TOKEN$(2);
  59.     COLOR CLF(0),CLB(0): LOCATE 25,48
  60.     CALL SCREEN.INPUT((25),(POS(0)),1,"",A$,"12"): CALL CLEAR.LINE
  61.     IF A$="1" THEN RESTORE PATTERN1.DATA ELSE RESTORE PATTERN2.DATA
  62.     COLOR CLF(1),CLB(1): LOCATE 3,45: PRINT PLAYER$(1);
  63.     COLOR CLF(2),CLB(2): LOCATE 3,60: PRINT PLAYER$(2);
  64.     FOR A=1 TO 4: READ B,C,D: CALL DISPLAY.PIECES(B,C,D): NEXT
  65.     CALL PRINT.MSG((PLAYER$(1)+"  (H)eads or (T)ails? "),(1))
  66.     CALL SCREEN.INPUT((25),(POS(0)),1,"",A$,"HT")
  67.     CALL MAKE.SOUND((5)): CALL WAIT.HERE((.25!))
  68.     A=INT(RND(0)*2)+1: IF A=1 THEN B$="It's Heads " ELSE B$="It's Tails "
  69.     IF (A=1 AND A$="H") OR (A=2 AND A$="T") THEN CUR.PLYR=1 ELSE CUR.PLYR=2
  70.     CALL PRINT.MSG((B$+PLAYER$(CUR.PLYR)+" Goes first."),CUR.PLYR)
  71.     CALL WAIT.HERE((3!)): CUR.PLYR=CUR.PLYR XOR 3: MOVE.NUM=1
  72. NEXT.PLAYER:
  73.     IF SCORE(1)+SCORE(2)=64 THEN END.FLG=1: GOTO GAME.OVER
  74.     CUR.PLYR=CUR.PLYR XOR 3: LOOK.FLG=0: GOSUB FIND.MOVES
  75.     IF MOVE.FLG=-1 THEN END.FLG=2: GOTO GAME.OVER
  76.     IF MOVE.FLG=0 THEN IF END.FLG THEN GOTO GAME.OVER ELSE END.FLG=1: GOTO NEXT.PLAYER
  77.     CALL MAKE.SOUND((2)): END.FLG=0
  78.     CALL PRINT.MSG(("It's "+PLAYER$(CUR.PLYR)+"'s turn"),CUR.PLYR)
  79.     IF PLAYER$(CUR.PLYR)="COMPUTER" THEN
  80.         FOR A=1 TO 64: BAD!(A,0)=1: BAD!(A,1)=1: NEXT: GOSUB COMPUTER.MOVE
  81.         CUR.MOVE=CUR.MOVE-1: X=(CUR.MOVE MOD 8)+1: Y=INT(CUR.MOVE/8)
  82.         FOR A=1 TO 4:
  83.             LOCATE Y*2+2,X*5-3: PRINT TOKEN$(CUR.PLYR);: CALL WAIT.HERE((.25!))
  84.             LOCATE Y*2+2,X*5-3: PRINT TOKEN$(0);: CALL WAIT.HERE((.25!))
  85.         NEXT: CALL CLEAR.LINE: GOTO MAKE.MOVE
  86.     END IF: IF CUR.PLYR=1 THEN M4=&H2200 ELSE M4=&H4400
  87.     CALL MOUSE((10),(0),(-1),M4)
  88.     X=0: Y=-1: IF CUR.PLYR=1 THEN X1=4: Y1=3 ELSE X1=4: Y1=4
  89. NEXT.PLAYER.1:
  90.     CALL GET.MOVEMENT(DIR): IF DIR=8 THEN GOTO MAKE.MOVE
  91.     IF DIR>256 THEN
  92.         DIR=DIR-256: A=INT(DIR/16)*8+(DIR MOD 16)
  93.         IF BOARD(A,0)>=0 THEN CALL MAKE.SOUND((1)): GOTO NEXT.PLAYER.1
  94.         IF X>0 AND Y>=0 THEN LOCATE Y*2+2,X*5-2: PRINT "  ";
  95.         X=DIR MOD 16: Y=INT(DIR/16): GOTO MAKE.MOVE
  96.     END IF
  97.     IF DIR=9 THEN GOSUB RESTART: GOTO NEXT.PLAYER.1
  98.     IF DIR=10 THEN CALL DISPLAY.HELP: GOTO NEXT.PLAYER.1
  99.     IF DIR=11 THEN IF MOVE.NUM>3-PLAYERS THEN CALL UNDO.MOVE: GOTO NEXT.PLAYER_
  100.     ELSE CALL MAKE.SOUND((1)): GOTO NEXT.PLAYER.1
  101. NEXT.PLAYER.2:
  102.     X1=X1+DIR(DIR,0): Y1=Y1+DIR(DIR,1)
  103. NEXT.PLAYER.3:
  104.     IF X1=9 THEN X1=1: IF DIR(DIR,0)=1 THEN Y1=Y1+1
  105.     IF Y1=8 THEN Y1=0: IF DIR(DIR,1)=1 THEN X1=X1+1: GOTO NEXT.PLAYER.3
  106. NEXT.PLAYER.4:
  107.     IF X1=0 THEN X1=8: IF DIR(DIR,0)=-1 THEN Y1=Y1-1
  108.     IF Y1=-1 THEN Y1=7: IF DIR(DIR,1)=-1 THEN X1=X1-1: GOTO NEXT.PLAYER.4
  109.     A=Y1*8+X1: IF BOARD(A,0)>0 THEN GOTO NEXT.PLAYER.2
  110.     IF X>0 AND Y>=0 THEN LOCATE Y*2+2,X*5-2: PRINT "  "; ELSE MOVE.FLG=1
  111.     X=X1: Y=Y1: LOCATE Y*2+2,X*5-2: PRINT MID$(TOKEN$(CUR.PLYR),2,2);
  112.     CALL MAKE.SOUND((3)): GOTO NEXT.PLAYER.1
  113. MAKE.MOVE:
  114.     IF X<1 OR Y<0 THEN CALL MAKE.SOUND((1)): GOTO NEXT.PLAYER.1
  115.     A=Y*8+X: IF BOARD(A,0)>=0 THEN CALL MAKE.SOUND((1)): GOTO NEXT.PLAYER.1
  116.     IF HELP.FLG THEN CALL DISPLAY.HELP
  117.     FOR A=1 TO 64
  118.         IF BOARD(A,0)<0 THEN BOARD(A,0)=0
  119.         BOARD(A,MOVE.NUM)=BOARD(A,0)
  120.     NEXT: BOARD(0,MOVE.NUM)=CUR.PLYR: GOSUB UPDATE.MOVE
  121.     MOVE.NUM=MOVE.NUM+1: GOTO NEXT.PLAYER
  122. REM *************************************************************************
  123. GAME.OVER:
  124.     IF END.FLG=2 THEN MSG$=PLAYER$(CUR.PLYR)+" HAS BEEN SKUNKED. " ELSE MSG$=""
  125.     IF SCORE(1)>SCORE(2) THEN MSG$=MSG$+PLAYER$(1)+" HAS WON. ": A=1_
  126.     ELSE IF SCORE(1)<SCORE(2) THEN MSG$=MSG$+PLAYER$(2)+" HAS WON. ": A=2_
  127.     ELSE MSG$="IT'S A TIE. ":A=0
  128.     COLOR CLF(A),CLB(A)
  129.     CALL CLEAR.LINE: PRINT MSG$;: CALL MAKE.SOUND((5)): GOSUB UPDATE.SCORES
  130. REM *************************************************************************
  131. REM ** END OF PROGRAM **
  132. END.PROGRAM:
  133.     CALL PRINT.MSG(("Play again (Y or N)? "),(0))
  134.     CALL SCREEN.INPUT((25),(POS(0)),1,"",A$,"YN")
  135.     IF A$="Y" THEN GOTO START ELSE CALL MAKE.SOUND((4))
  136.     END
  137. PROGRAM.ERROR:
  138.     CALL CLEAR.LINE((23),(25)): LOCATE 24,1: PRINT "Program error #";ERR;
  139.     CALL MAKE.SOUND((2)): LOCATE 25,1: PRINT "Push any key to end program";
  140.     WHILE INKEY$="": WEND: CALL MAKE.SOUND((5))
  141.     END
  142. REM *************************************************************************
  143. REM ** START OF SUBROUTINES **
  144. PRINT.INSTR:
  145.     IF CLF(3)<>7 THEN COLOR 2,0
  146.     CLS: PRINT "                   O T H E L L O ": PRINT
  147.     PRINT "   Computer Othello is a game played on an 8 by 8 game board."
  148.     PRINT "The object of the game is to `capture' more  squares than"
  149.     PRINT "your opponent by outflanking his squares with your squares."
  150.     PRINT
  151.     PRINT "   The squares along the wall are valuable because they can"
  152.     PRINT "only be `outflanked' in one direction. The corner can not be"
  153.     PRINT "recaptured after it has been taken.  It is the most important"
  154.     PRINT "square to capture.
  155.     PRINT "   One strategy to use is to avoid any square adjacent to"
  156.     PRINT "the wall, while you try to capture wall squares."
  157.     PRINT
  158.     PRINT
  159.     PRINT "To select move:"
  160.     PRINT "      Use arrow keys or joystick to select desired square."
  161.     PRINT "      Then press <RETURN>, <SPACE> or joystick button to make move."
  162.     PRINT "Other options:"
  163.     PRINT "      Press <H> (for help) to show all possible moves."
  164.     PRINT "      Press <U> to undo last move."
  165.     PRINT "      Press <ESC> to abort game."
  166.     LOCATE 25,1: PRINT "                 Press any key to continue. . . .";
  167.     CALL MAKE.SOUND((1)): WHILE INKEY$="": WEND: CALL MAKE.SOUND((3)): RETURN
  168. DRAW.BOARD:
  169.     RESTORE BOARD.DATA
  170.     READ A$,B$,C$,D$,TOKEN$(0),TOKEN$(1),TOKEN$(2)
  171.     IF CLF(3)<>7 THEN TOKEN$(2)=TOKEN$(1)
  172.     COLOR CLF(3),CLB(3): CLS: PRINT A$;
  173.     FOR A=1 TO 7: PRINT B$;: PRINT C$;: NEXT
  174.     PRINT B$;: PRINT D$;
  175.     COLOR CLF(1),CLB(1): LOCATE 1,51: PRINT TOKEN$(1);
  176.     LOCATE 2,44: PRINT CHR$(200)+STRING$(10,205)+CHR$(188);
  177.     COLOR CLF(2),CLB(2): LOCATE 1,66: PRINT TOKEN$(2);
  178.     LOCATE 2,59: PRINT CHR$(200)+STRING$(10,205)+CHR$(188);
  179.     COLOR CLF(4),0: LOCATE 18,15: PRINT "O T H E L L O";
  180.     COLOR 7,0: RETURN
  181. FIND.MOVES:
  182.     MOVE.FLG=-1
  183.     FOR Y=0 TO 7
  184.         FOR X=1 TO 8
  185.             A=Y*8+X: Z=0
  186.             IF BOARD(A,0)=CUR.PLYR THEN
  187.                 IF MOVE.FLG=-1 THEN MOVE.FLG=0
  188.             ELSEIF BOARD(A,0)=0 THEN
  189.                 WHILE Z<8: X1=X: Y1=Y: C=0
  190. FIND.MOVE.2:
  191.                     X1=X1+DIR(Z,0): Y1=Y1+DIR(Z,1): B=Y1*8+X1
  192.                     IF X1<1 OR X1>8 OR Y1<0 OR Y1>7 THEN GOTO FIND.MOVE.1
  193.                     IF BOARD(B,0)<=0 THEN GOTO FIND.MOVE.1
  194.                     IF BOARD(B,0)=(CUR.PLYR XOR 3) THEN C=C+1: GOTO FIND.MOVE.2
  195.                     IF C>0 THEN BOARD(A,0)=BOARD(A,0)-C: MOVE.FLG=1
  196. FIND.MOVE.1:
  197.                     Z=Z+1
  198.                 WEND
  199.             END IF
  200.         NEXT
  201.     NEXT: IF MOVE.FLG<>0 OR LOOK.FLG=1 THEN RETURN
  202.     CALL PRINT.MSG((PLAYER$(CUR.PLYR)+" must pass"),CUR.PLYR)
  203.     CALL MAKE.SOUND((7)): CALL WAIT.HERE((1!)): RETURN
  204. UPDATE.MOVE:
  205.     Z=0: B=10
  206.     WHILE Z<8: X1=X: Y1=Y: C=0
  207. UPDATE.MOVE.2:
  208.         X1=X1+DIR(Z,0): Y1=Y1+DIR(Z,1): A=Y1*8+X1
  209.         IF X1<1 OR X1>8 OR Y1<0 OR Y1>7 THEN GOTO UPDATE.MOVE.1
  210.         IF BOARD(A,0)=0 THEN GOTO UPDATE.MOVE.1
  211.         IF BOARD(A,0)=(CUR.PLYR XOR 3) THEN C=C+1: GOTO UPDATE.MOVE.2
  212.         FOR A=1 TO C
  213.             X1=X1-DIR(Z,0): Y1=Y1-DIR(Z,1)
  214.             CALL MAKE.SOUND(B): CALL DISPLAY.PIECES(X1,Y1,CUR.PLYR)
  215.             B=B+1: CALL WAIT.HERE((.25!))
  216.         NEXT
  217. UPDATE.MOVE.1:
  218.         Z=Z+1
  219.     WEND: CALL MAKE.SOUND((B)): CALL DISPLAY.PIECES(X,Y,CUR.PLYR): RETURN
  220. COMPUTER.MOVE:
  221.     CALL CLEAR.LINE: PRINT "Quiet I'm thinking!  ";
  222.     RESTORE COMPUTER.MOVE.DATA: CUR.MOVE=0: WEIGHT!=0: OTH.PLYR=CUR.PLYR XOR 3
  223. REM ** SELF DEFENSE **
  224.     FOR A=1 TO 4: READ FST,STP
  225.         FOR B=1 TO 8: SIDE(B,0)=BOARD(FST,0): SIDE(B,1)=FST: FST=FST+STP: NEXT
  226.         FOR MOVE=2 TO 7
  227.             IF SIDE(MOVE,0)<0 THEN
  228.                 C=0
  229.                 FOR B=MOVE+1 TO 8
  230.                     IF SIDE(B,0)<=0 THEN
  231.                         C=1: B=8
  232.                     ELSEIF SIDE(B,0)=OTH.PLYR THEN
  233.                         C=2: B=8
  234.                     END IF
  235.                 NEXT
  236.                 FOR B=MOVE-1 TO 1 STEP -1
  237.                     IF SIDE(B,0)<=0 THEN
  238.                         B=1: IF C=2 THEN C=4
  239.                     ELSEIF SIDE(B,0)=OTH.PLYR THEN
  240.                         B=1: IF C=1 THEN C=4
  241.                     END IF
  242.                 NEXT: IF C=4 THEN BAD!(SIDE(MOVE,1),0)=.4
  243.             ELSEIF SIDE(MOVE,0)=CUR.PLYR AND CUR.MOVE=0 THEN
  244.                 IF MOVE>2 AND SIDE(MOVE-1,0)=OTH.PLYR THEN
  245.                     STP=-1: LST=1: FST=8
  246.                 ELSEIF MOVE<7 AND SIDE(MOVE+1,0)=OTH.PLYR THEN
  247.                     STP=1: LST=8: FST=1
  248.                 ELSE
  249.                     GOTO NEXT.SIDE
  250.                 END IF
  251.                 FOR B=MOVE+STP*2 TO LST STEP STP
  252.                     IF SIDE(B,0)<0 THEN
  253.                         C=0
  254.                         IF B<>LST THEN
  255.                             FOR D=B+STP TO LST STEP STP
  256.                                 IF SIDE(D,0)<=0 THEN C=C OR 1
  257.                                 IF SIDE(D,0)=OTH.PLYR AND (C AND 1)=0 THEN C=C OR 2
  258.                                 IF SIDE(D,0)=CUR.PLYR THEN_
  259.                                     IF D=B+STP*2 AND (C AND 1)=1 THEN C=C OR 8_
  260.                                     ELSE IF (C AND 3)=2 THEN C=C OR 4
  261.                             NEXT
  262.                             FOR D=MOVE TO FST STEP -STP
  263.                                 IF SIDE(D,0)<=0 THEN C=C OR 16
  264.                                 IF SIDE(D,0)=OTH.PLYR AND (C AND 16)=0 THEN C=C OR 32
  265.                                 IF SIDE(D,0)=CUR.PLYR AND D=MOVE-STP*2 AND (C AND 16) THEN C=C OR 64
  266.                             NEXT
  267.                         END IF
  268.                         IF C=0 THEN
  269.                             CUR.MOVE=SIDE(B,1)
  270.                         ELSEIF C AND 2 THEN
  271.                             IF (C AND 32)=32 OR (C AND 16)=0 OR (C AND 4)=4 THEN_
  272.                                 CUR.MOVE=SIDE(B,1) ELSE BAD!(SIDE(B,1),0)=.5
  273.                         ELSEIF C AND 32 THEN
  274.                             IF (C AND 1)=0 THEN_
  275.                                 CUR.MOVE=SIDE(B,1) ELSE BAD!(SIDE(B,1),0)=.5
  276.                         ELSEIF C AND 8 THEN
  277.                             IF (C AND 16)=0 AND (C AND 32)=0 THEN CUR.MOVE=SIDE(B,1)
  278.                         ELSEIF (C AND 64)=0 THEN
  279.                             CUR.MOVE=SIDE(B,1)
  280.                         END IF: IF CUR.MOVE>0 THEN BAD!(CUR.MOVE,0)=1
  281.                         B=LST
  282.                     ELSEIF SIDE(B,0)=CUR.PLYR THEN
  283.                         B=LST
  284.                     END IF
  285.                 NEXT
  286.             END IF
  287. NEXT.SIDE:
  288.         NEXT: CALL MAKE.SOUND((8)): PRINT ".";
  289.     NEXT: IF CUR.MOVE>0 AND BAD!(CUR.MOVE,1)>=1 THEN GOTO COMPUTER.MOVE.0
  290. REM ** TRY TO MOVE TO SIDE & SET TRAPS **
  291.     FOR A=1 TO 4: READ FST,STP: C=0
  292.         FOR B=1 TO 8: SIDE(B,0)=BOARD(FST,0): SIDE(B,1)=FST: FST=FST+STP: NEXT
  293. REM ** CHECK IF OTH.PLYR IS ON THIS SIDE **
  294.         FOR B=1 TO 8
  295.             IF SIDE(B,0)=CUR.PLYR THEN C=C OR 1_
  296.                 ELSE IF SIDE(B,0)=OTH.PLYR THEN C=C OR 2
  297.         NEXT: IF C<>2 THEN C=1
  298.         FOR MOVE=2 TO 7
  299.             IF SIDE(MOVE,0)<0 THEN
  300.             A!=C
  301. REM ******* CHECK FOR 0█Ox█X00 **
  302.                 IF MOVE>2 AND MOVE<7 THEN
  303.                     IF SIDE(MOVE-1,0)=OTH.PLYR AND SIDE(MOVE-2,0)<=0_
  304.                     AND SIDE(MOVE+1,0)<=0 AND SIDE(MOVE+2,0)=CUR.PLYR THEN
  305.                         MOVE.FLG=1
  306.                         IF MOVE>3 THEN IF SIDE(MOVE-3,0)=OTH.PLYR THEN MOVE.FLG=3
  307.                         FOR B=MOVE+2 TO 8
  308.                             IF SIDE(B,0)<=0 THEN
  309.                                 IF MOVE.FLG AND 2 THEN MOVE.FLG=0: B=8 ELSE B=8
  310.                             ELSEIF SIDE(B,0)=OTH.PLYR THEN
  311.                                 MOVE.FLG=0: B=8
  312.                             END IF
  313.                         NEXT
  314.                         IF MOVE.FLG AND 1 THEN
  315.                             BAD!(SIDE(MOVE,1),0)=1
  316.                             IF MOVE=3 THEN A!=A!*16 ELSE A!=A!*10
  317.                             GOTO FOUND.MOVE
  318.                         END IF
  319.                     END IF
  320.                     IF SIDE(MOVE+1,0)=OTH.PLYR AND SIDE(MOVE+2,0)<=0_
  321.                     AND SIDE(MOVE-1,0)<=0 AND SIDE(MOVE-2,0)=CUR.PLYR THEN
  322.                         MOVE.FLG=1
  323.                         IF MOVE<6 THEN IF SIDE(MOVE+3,0)=OTH.PLYR THEN MOVE.FLG=3
  324.                         FOR B=MOVE-2 TO 1 STEP -1
  325.                             IF SIDE(B,0)<=0 THEN
  326.                                 IF MOVE.FLG AND 2 THEN MOVE.FLG=0: B=1 ELSE B=1
  327.                             ELSEIF SIDE(B,0)=OTH.PLYR THEN
  328.                                 MOVE.FLG=0: B=1
  329.                             END IF
  330.                         NEXT
  331.                         IF MOVE.FLG AND 1 THEN
  332.                             BAD!(SIDE(MOVE,1),0)=1
  333.                             IF MOVE=6 THEN A!=A!*16 ELSE A!=A!*10
  334.                             GOTO FOUND.MOVE
  335.                         END IF
  336.                     END IF
  337.                 END IF
  338. REM ******* X█x IS BAD ** OK **
  339.                 IF MOVE>2 THEN_
  340.                     IF SIDE(MOVE-1,0)<=0 AND SIDE(MOVE-2,0)=CUR.PLYR THEN_
  341.                         BAD!(SIDE(MOVE,1),0)=.9
  342.                 IF MOVE<7 THEN_
  343.                     IF SIDE(MOVE+1,0)<=0 AND SIDE(MOVE+2,0)=CUR.PLYR THEN_
  344.                         BAD!(SIDE(MOVE,1),0)=.9
  345. REM ******* CHECK FOR █O██x ** OK **
  346.                 IF MOVE=5 THEN
  347.                     IF SIDE(MOVE-1,0)<=0 AND SIDE(MOVE-2,0)<=0_
  348.                     AND SIDE(MOVE-3,0)=OTH.PLYR AND SIDE(1,0)<=0 THEN
  349.                         MOVE.FLG=1
  350.                         FOR B=MOVE+1 TO 8
  351.                             IF SIDE(B,0)=OTH.PLYR THEN
  352.                                 MOVE.FLG=0: B=8
  353.                             ELSEIF SIDE(B,0)<=0 THEN
  354.                                 B=8
  355.                             END IF
  356.                         NEXT: IF MOVE.FLG THEN A!=A!*10: GOTO FOUND.MOVE
  357.                     END IF
  358.                 ELSEIF MOVE=4 THEN
  359.                     IF SIDE(MOVE+1,0)<=0 AND SIDE(MOVE+2,0)<=0_
  360.                     AND SIDE(MOVE+3,0)=OTH.PLYR AND SIDE(8,0)<=0 THEN
  361.                         MOVE.FLG=1
  362.                         FOR B=MOVE-1 TO 1 STEP -1
  363.                             IF SIDE(B,0)=OTH.PLYR THEN
  364.                                 MOVE.FLG=0: B=1
  365.                             ELSEIF SIDE(B,0)<=0 THEN
  366.                                 B=1
  367.                             END IF
  368.                         NEXT: IF MOVE.FLG THEN A!=A!*10: GOTO FOUND.MOVE
  369.                     END IF
  370.                 END IF
  371. REM ******* CHECK FOR Ox? OR ?xO **
  372.                 IF SIDE(MOVE-1,0)=OTH.PLYR THEN
  373.                     MOVE.FLG=0
  374.                     FOR B=MOVE+1 TO 8
  375.                         IF SIDE(B,0)<=0 THEN
  376.                             B=8: IF MOVE.FLG=0 OR MOVE.FLG=3 THEN MOVE.FLG=2
  377.                         ELSEIF SIDE(B,0)=OTH.PLYR THEN
  378.                             IF MOVE.FLG=3 THEN MOVE.FLG=1: B=8 ELSE MOVE.FLG=1
  379.                         ELSEIF SIDE(B,0)=CUR.PLYR AND MOVE.FLG=1 THEN
  380.                             MOVE.FLG=3
  381.                     END IF
  382.                     NEXT
  383.                     IF MOVE.FLG=0 THEN A!=A!*4
  384.                     IF MOVE.FLG=1 THEN A!=A!*5
  385.                     IF MOVE.FLG=2 THEN BAD!(SIDE(MOVE,1),0)=.6
  386.                     IF MOVE.FLG=3 THEN A!=A!*8
  387.                     GOTO FOUND.MOVE
  388.                 ELSEIF SIDE(MOVE+1,0)=OTH.PLYR THEN
  389.                     MOVE.FLG=0
  390.                     FOR B=MOVE-1 TO 1 STEP -1
  391.                         IF SIDE(B,0)<=0 THEN
  392.                             B=1: IF MOVE.FLG=0 OR MOVE.FLG=3 THEN MOVE.FLG=2
  393.                         ELSEIF SIDE(B,0)=OTH.PLYR THEN
  394.                             IF MOVE.FLG=3 THEN MOVE.FLG=1: B=1 ELSE MOVE.FLG=1
  395.                         ELSEIF SIDE(B,0)=CUR.PLYR AND MOVE.FLG=1 THEN
  396.                             MOVE.FLG=3
  397.                         END IF
  398.                     NEXT
  399.                     IF MOVE.FLG=0 THEN A!=A!*4
  400.                     IF MOVE.FLG=1 THEN A!=A!*5
  401.                     IF MOVE.FLG=2 THEN BAD!(SIDE(MOVE,1),0)=.6
  402.                     IF MOVE.FLG=3 THEN A!=A!*8
  403.                     GOTO FOUND.MOVE
  404.                 END IF
  405. REM ******* AVOID █x██O **
  406.                 IF MOVE=2 THEN
  407.                     IF SIDE(1,0)<=0 AND SIDE(MOVE+1,0)<=0_
  408.                     AND SIDE(MOVE+2,0)<=0 AND SIDE(MOVE+3,0)<>CUR.PLYR THEN_
  409.                         BAD!(SIDE(MOVE,1),0)=.1: GOTO FOUND.MOVE
  410.                 ELSEIF MOVE=7 THEN
  411.                     IF SIDE(8,0)<=0 AND SIDE(MOVE-1,0)<=0_
  412.                     AND SIDE(MOVE-2,0)<=0 AND SIDE(MOVE-3,0)<>CUR.PLYR THEN_
  413.                         BAD!(SIDE(MOVE,1),0)=.1: GOTO FOUND.MOVE
  414.                 END IF
  415. REM ******* CHECK FOR ??x??x?? ** OK **
  416.                 IF MOVE=3 OR MOVE=6 THEN
  417.                     A!=A!*4
  418. REM ******* ALL OTHERS ** OK **
  419.                 ELSEIF MOVE=2 OR MOVE=7 THEN
  420.                     IF C>1 THEN A!=A!*2 ELSE A!=.25
  421.                 ELSE
  422.                     A!=A!*3
  423.                 END IF
  424. FOUND.MOVE:
  425.                 NEW.MOVE=SIDE(MOVE,1)
  426.                 IF ((MOVE=2 AND SIDE(1,0)=OTH.PLYR) OR (MOVE=7 AND SIDE(8,0)=OTH.PLYR))_
  427.                 AND BAD!(NEW.MOVE,0)>=1 AND BAD!(NEW.MOVE,1)>=1 THEN A!=A!*2
  428. REM ** CHOOSE BETTER MOVE **
  429.                 A!=ABS(BOARD(NEW.MOVE,0))*BAD!(NEW.MOVE,1)*A!
  430.                 IF CUR.MOVE=0 OR BAD!(NEW.MOVE,1)>BAD!(CUR.MOVE,1) THEN
  431.                     CUR.MOVE=NEW.MOVE: WEIGHT!=A!
  432.                 ELSEIF BAD!(NEW.MOVE,1)=BAD!(CUR.MOVE,1) THEN
  433.                     IF BAD!(NEW.MOVE,0)>BAD!(CUR.MOVE,0) THEN
  434.                         CUR.MOVE=NEW.MOVE: WEIGHT!=A!
  435.                     ELSEIF BAD!(NEW.MOVE,0)=BAD!(CUR.MOVE,0) THEN
  436.                         IF A!>WEIGHT! OR (A!=WEIGHT! AND INT(RND(0)*3)+1=2) THEN_
  437.                             CUR.MOVE=NEW.MOVE: WEIGHT!=A!
  438.                     END IF
  439.                 END IF
  440.             END IF
  441.         NEXT: CALL MAKE.SOUND((8)): PRINT ".";
  442.     NEXT
  443.     IF CUR.MOVE>0 AND BAD!(CUR.MOVE,0)>=1 AND BAD!(CUR.MOVE,1)>=1 THEN GOTO COMPUTER.MOVE.0
  444. REM ** CHECK FOUR CORNERS **
  445.     FOR A=1 TO 4: READ NEW.MOVE
  446.         IF BOARD(NEW.MOVE,0)<0 AND (CUR.MOVE=0 OR BAD!(CUR.MOVE,0)<1) THEN_
  447.             CUR.MOVE=NEW.MOVE: WEIGHT!=1
  448.     NEXT: CALL MAKE.SOUND((8)): PRINT ".";
  449. REM ** CHECK INNER SQUARE **
  450.     FOR A=1 TO 12: READ NEW.MOVE
  451.         IF BOARD(NEW.MOVE,0)<0 THEN
  452. REM ** CHOOSE BETTER MOVE **
  453.             IF A<5 THEN A!=3 ELSE A!=2.5
  454.             A!=ABS(BOARD(NEW.MOVE,0))*BAD!(NEW.MOVE,1)*A!
  455.             IF CUR.MOVE=0 OR BAD!(NEW.MOVE,1)>BAD!(CUR.MOVE,1) THEN
  456.                 CUR.MOVE=NEW.MOVE: WEIGHT!=A!
  457.             ELSEIF BAD!(NEW.MOVE,1)=BAD!(CUR.MOVE,1) THEN
  458.                 IF BAD!(NEW.MOVE,0)>BAD!(CUR.MOVE,0) THEN
  459.                     CUR.MOVE=NEW.MOVE: WEIGHT!=A!
  460.                 ELSEIF BAD!(NEW.MOVE,0)=BAD!(CUR.MOVE,0) THEN
  461.                     IF A!>WEIGHT! OR (A!=WEIGHT! AND INT(RND(0)*3)+1=2) THEN_
  462.                         CUR.MOVE=NEW.MOVE: WEIGHT!=A!
  463.                 END IF
  464.             END IF
  465.         END IF
  466.     NEXT: CALL MAKE.SOUND((8)): PRINT ".";
  467.     IF CUR.MOVE>0 AND BAD!(CUR.MOVE,0)>=1 AND BAD!(CUR.MOVE,1)>=1 THEN GOTO COMPUTER.MOVE.0
  468. REM ** CHECK OUTER SQUARE **
  469.     FOR A=1 TO 4: READ FST,STP: C=0: A!=1
  470.         FOR B=1 TO 8
  471.             IF BOARD(FST,0)=CUR.PLYR THEN C=C OR 2
  472.             IF BOARD(FST,0)=OTH.PLYR THEN C=C OR 1
  473.             FST=FST+STP
  474.         NEXT: READ NEW.MOVE,STP
  475.         FOR B=1 TO 4
  476.             IF C=0 THEN A!=.25 ELSE IF C=1 THEN A!=.5 ELSE A!=C
  477.             IF BOARD(NEW.MOVE,0)<0 THEN
  478. REM ** CHOOSE BETTER MOVE **
  479.                 A!=ABS(BOARD(NEW.MOVE,0))*BAD!(NEW.MOVE,1)*A!
  480.                 IF CUR.MOVE=0 OR BAD!(NEW.MOVE,1)>BAD!(CUR.MOVE,1) THEN
  481.                     CUR.MOVE=NEW.MOVE: WEIGHT!=A!
  482.                 ELSEIF BAD!(NEW.MOVE,1)=BAD!(CUR.MOVE,1) THEN
  483.                     IF BAD!(NEW.MOVE,0)>BAD!(CUR.MOVE,0) THEN
  484.                         CUR.MOVE=NEW.MOVE: WEIGHT!=A!
  485.                     ELSEIF BAD!(NEW.MOVE,0)=BAD!(CUR.MOVE,0) THEN
  486.                         IF A!>WEIGHT! OR (A!=WEIGHT! AND INT(RND(0)*3)+1=2) THEN_
  487.                             CUR.MOVE=NEW.MOVE: WEIGHT!=A!
  488.                     END IF
  489.                 END IF
  490.             END IF: NEW.MOVE=NEW.MOVE+STP
  491.         NEXT
  492.     NEXT: CALL MAKE.SOUND((8)): PRINT ".";
  493.     IF CUR.MOVE>0 AND BAD!(CUR.MOVE,0)>=1 AND BAD!(CUR.MOVE,1)>=1 THEN GOTO COMPUTER.MOVE.0
  494. REM ** CHECK FOUR CORNERS AND TAKE 10 15 50 55 IF TAKEN **
  495.     FOR A=1 TO 4: READ B,NEW.MOVE
  496.         IF BOARD(B,0)>0 THEN
  497.             IF BOARD(NEW.MOVE,0)<0 THEN
  498. REM ** CHOOSE BETTER MOVE **
  499.                 A!=ABS(BOARD(NEW.MOVE,0))*BAD!(NEW.MOVE,1)
  500.                 IF CUR.MOVE=0 OR BAD!(NEW.MOVE,1)>BAD!(CUR.MOVE,1) THEN
  501.                     CUR.MOVE=NEW.MOVE: WEIGHT!=A!
  502.                 ELSEIF BAD!(NEW.MOVE,1)=BAD!(CUR.MOVE,1) THEN
  503.                     IF BAD!(NEW.MOVE,0)>BAD!(CUR.MOVE,0) THEN
  504.                         CUR.MOVE=NEW.MOVE: WEIGHT!=A!
  505.                     ELSEIF BAD!(NEW.MOVE,0)=BAD!(CUR.MOVE,0) THEN
  506.                         IF A!>WEIGHT! OR (A!=WEIGHT! AND INT(RND(0)*3)+1=2) THEN_
  507.                             CUR.MOVE=NEW.MOVE: WEIGHT!=A!
  508.                     END IF
  509.                 END IF
  510.             END IF
  511.         END IF
  512.     NEXT: CALL MAKE.SOUND((8)): PRINT ".";
  513.     IF CUR.MOVE>0 AND BAD!(CUR.MOVE,0)>=1 AND BAD!(CUR.MOVE,1)>=1 THEN GOTO COMPUTER.MOVE.0
  514. REM ** CHECK 10 15 50 55 **
  515.     FOR A=1 TO 4: READ NEW.MOVE: BAD!(NEW.MOVE,0)=.3
  516.         IF BOARD(NEW.MOVE,0)<0 THEN
  517. REM ** CHOOSE BETTER MOVE **
  518.             A!=ABS(BOARD(NEW.MOVE,0))*BAD!(NEW.MOVE,1)
  519.             IF CUR.MOVE=0 OR BAD!(NEW.MOVE,1)>BAD!(CUR.MOVE,1) THEN
  520.                 CUR.MOVE=NEW.MOVE: WEIGHT!=A!
  521.             ELSEIF BAD!(NEW.MOVE,1)=BAD!(CUR.MOVE,1) THEN
  522.                 IF BAD!(NEW.MOVE,0)>BAD!(CUR.MOVE,0) THEN
  523.                     CUR.MOVE=NEW.MOVE: WEIGHT!=A!
  524.                 ELSEIF BAD!(NEW.MOVE,0)=BAD!(CUR.MOVE,0) THEN
  525.                     IF A!>WEIGHT! OR (A!=WEIGHT! AND INT(RND(0)*3)+1=2) THEN_
  526.                         CUR.MOVE=NEW.MOVE: WEIGHT!=A!
  527.                 END IF
  528.             END IF
  529.         END IF
  530.     NEXT
  531. COMPUTER.MOVE.0:
  532.     IF BAD!(CUR.MOVE,1)<1 THEN RETURN ELSE LOOK.FLG=0
  533.     RESTORE COMPUTER.MOVE.DATA.1
  534.     FOR A=1 TO 4: READ B,C,D,E
  535.         IF BOARD(B,0)<=0 THEN_
  536.             IF BOARD(C,0)>0 OR BOARD(D,0)>0 OR BOARD(E,0)>0_
  537.             OR CUR.MOVE=C OR CUR.MOVE=D OR CUR.MOVE=E THEN LOOK.FLG=1
  538.     NEXT: IF LOOK.FLG=0 THEN RETURN
  539.     FOR A=1 TO 64
  540.         CUR.BOARD(A,0)=BOARD(A,0)
  541.         IF BOARD(A,0)<0 THEN BOARD(A,0)=0
  542.     NEXT: CUR.PLYR=CUR.PLYR XOR 3: GOSUB FIND.MOVES
  543.     FOR A=1 TO 64
  544.         CUR.BOARD(A,1)=BOARD(A,0)
  545.         IF CUR.BOARD(A,0)>=0 THEN BOARD(A,0)=CUR.BOARD(A,0) ELSE BOARD(A,0)=0
  546.     NEXT: CUR.PLYR=CUR.PLYR XOR 3
  547.     X=((CUR.MOVE-1) MOD 8)+1: Y=INT((CUR.MOVE-1)/8): Z=0
  548.     WHILE Z<8: X1=X: Y1=Y: C=0
  549. COMPUTER.MOVE.2:
  550.         X1=X1+DIR(Z,0): Y1=Y1+DIR(Z,1): A=Y1*8+X1
  551.         IF X1<1 OR X1>8 OR Y1<0 OR Y1>7 THEN GOTO COMPUTER.MOVE.1
  552.         IF BOARD(A,0)=0 THEN GOTO COMPUTER.MOVE.1
  553.         IF BOARD(A,0)=(CUR.PLYR XOR 3) THEN C=C+1: GOTO COMPUTER.MOVE.2
  554.         FOR A=1 TO C
  555.             X1=X1-DIR(Z,0): Y1=Y1-DIR(Z,1): BOARD(X1+Y1*8,0)=CUR.PLYR
  556.         NEXT
  557. COMPUTER.MOVE.1:
  558.         Z=Z+1
  559.     WEND: BOARD(X+Y*8,0)=CUR.PLYR: CUR.PLYR=CUR.PLYR XOR 3: GOSUB FIND.MOVES
  560.     IF MOVE.FLG<1 THEN GOTO COMPUTER.RETURN
  561.     FOR A=1 TO 4: READ NEW.MOVE
  562.         IF CUR.BOARD(NEW.MOVE,0)<0 AND BOARD(NEW.MOVE,0)<0 THEN
  563.             CUR.MOVE=NEW.MOVE
  564.         ELSEIF BOARD(NEW.MOVE,0)<0 AND CUR.BOARD(NEW.MOVE,1)=0 THEN
  565.             BAD!(CUR.MOVE,1)=.001: CUR.MOVE=0
  566.         END IF
  567.     NEXT
  568. COMPUTER.RETURN:
  569.     FOR A=1 TO 64: BOARD(A,0)=CUR.BOARD(A,0): NEXT: CUR.PLYR=CUR.PLYR XOR 3
  570.     IF CUR.MOVE=0 THEN GOTO COMPUTER.MOVE ELSE RETURN
  571. RESTART:
  572.     CALL PRINT.MSG(("Abort game (Y or N)? "),(0))
  573.     CALL SCREEN.INPUT((25),(POS(0)),1,"N",A$,"YN")
  574.     IF A$="Y" THEN RETURN GAME.OVER
  575.     CALL PRINT.MSG(("It's "+PLAYER$(CUR.PLYR)+"'s turn"),CUR.PLYR): RETURN
  576. DISPLAY.SCORES:
  577.     LOCATE 5,44: COLOR CLF(4),CLB(4): PRINT"   Greatest Players Ever   "
  578.     COLOR CLF(5),CLB(5): LOCATE ,44
  579.     PRINT "    Name        Wins Losses": LOCATE ,44
  580.     PRINT "--------------  ----   ----"
  581.     FOR B=1 TO 9
  582.         LOCATE ,44: PRINT STR$(B)+"."+GP$(B);TAB(61);USING"###    ###";GP(B,0);GP(B,1)
  583.     NEXT
  584.     LOCATE ,44: PRINT "10."+GP$(10);TAB(61);USING"###    ###";GP(10,0);GP(10,1)
  585.     COLOR 7,0: RETURN
  586. UPDATE.SCORES:
  587.     IF A=0 OR END.FLG=0 THEN RETURN
  588.     CUR.PLYR=A: FOR A=1 TO 10: IF GP$(A)<>"" THEN NEXT: A=10 ELSE A=A-1
  589.     GOSUB UPDATE.SCORES.1: GP$(B)=PLAYER$(CUR.PLYR): GP(B,0)=GP(B,0)+1
  590.     CUR.PLYR=CUR.PLYR XOR 3
  591.     GOSUB UPDATE.SCORES.1: GP$(B)=PLAYER$(CUR.PLYR): GP(B,1)=GP(B,1)+1
  592.     FOR B=1 TO A
  593.         FOR C=B TO A
  594.             IF GP(C,0)/(GP(C,1)+.1)>GP(B,0)/(GP(B,1)+.1) THEN_
  595.                 SWAP GP$(B),GP$(C): SWAP GP(B,0),GP(C,0): SWAP GP(B,1),GP(C,1)
  596.         NEXT
  597.     NEXT: GOSUB PUT.SCORES: GOSUB DISPLAY.SCORES: RETURN
  598. UPDATE.SCORES.1:
  599.     FOR B=1 TO A: IF GP$(B)=PLAYER$(CUR.PLYR) THEN RETURN
  600.     NEXT: COLOR CLF(CUR.PLYR),CLB(CUR.PLYR)
  601.     CALL CLEAR.LINE: PRINT PLAYER$(CUR.PLYR)+"'s name not found.";
  602.     CALL PRINT.MSG("Enter number of player or <RETURN> if new player. ",CUR.PLYR)
  603.     CALL SCREEN.INPUT((25),(POS(0)),2,"",A$,"1234567890")
  604.     IF A$<>"" THEN IF VAL(A$)>A OR VAL(A$)<1 THEN GOTO UPDATE.SCORES.1_
  605.     ELSE B=VAL(A$): CALL CLEAR.LINE: RETURN
  606.     IF A<10 THEN A=A+1: B=A: CALL CLEAR.LINE: RETURN
  607. UPDATE.SCORES.2:
  608.     CALL CLEAR.LINE: PRINT "Top players list is full."
  609.     CALL PRINT.MSG("Enter number of player to delete or <RETURN> to not list new player. ",CUR.PLYR)
  610.     CALL SCREEN.INPUT((25),(POS(0)),2,"",A$,"1234567890")
  611.     IF A$<>"" THEN IF VAL(A$)>A OR VAL(A$)<1 THEN GOTO UPDATE.SCORES.2_
  612.     ELSE B=VAL(A$) ELSE B=0
  613.     CALL CLEAR.LINE: RETURN
  614. GET.SCORES:
  615.     ON ERROR GOTO GETERR
  616.     OPEN"R",1,"OTHELLO.TOP",512: FIELD 1,512 AS A$: GET 1,1
  617.     FOR A=1 TO 512: MID$(A$,A,1)=CHR$(ASC(MID$(A$,A,1)) XOR 255): NEXT
  618.     IF MID$(A$,1,3)="TOP" THEN
  619.         FOR A=1 TO 10
  620.             GP$(A)=FNS$(MID$(A$,A*14-10,10)): GP(A,0)=CVI(MID$(A$,A*14,2))
  621.             GP(A,1)=CVI(MID$(A$,A*14+2,2))
  622.         NEXT
  623.     ELSE
  624.         FOR A=1 TO 10: GP$(A)="": GP(A,0)=0: GP(A,1)=0: NEXT
  625.     END IF: CLOSE
  626. GETRET:
  627.     ON ERROR GOTO PROGRAM.ERROR: RETURN
  628. GETERR:
  629.     LOCATE 24,1: PRINT "PROBLEMS EXIST PREVENTING THE LOADING OF THE HIGH SCORES.";
  630.     LOCATE 25,1: PRINT "CORRECT PROBLEM AND PRESS 'ENTER' OR PRESS 'A' TO ABORT LOAD. ";
  631.     CALL SCREEN.INPUT((25),(POS(0)),1,"",A$,("A"+CHR$(13))): CALL CLEAR.LINE
  632.     LOCATE 25,1: PRINT SPACE$(79);: LOCATE 25,1
  633.     IF A$="" THEN RESUME GET.SCORES ELSE RESUME GETRET
  634. PUT.SCORES:
  635.     ON ERROR GOTO PUTERR
  636.     OPEN"R",1,"OTHELLO.TOP",512: FIELD 1,512 AS A$: B$="TOP"
  637.     FOR A=1 TO 10
  638.         B$=B$+GP$(A)+SPACE$(10-LEN(GP$(A)))+MKI$(GP(A,0))+MKI$(GP(A,1))
  639.     NEXT: B$=B$+SPACE$(512-LEN(B$))
  640.     FOR A=1 TO 255: MID$(B$,A,1)=CHR$(ASC(MID$(B$,A,1)) XOR 255): NEXT
  641.     LSET A$=B$: PUT 1,1: CLOSE
  642. PUTRET:
  643.     ON ERROR GOTO PROGRAM.ERROR: RETURN
  644. PUTERR:
  645.     LOCATE 24,1: PRINT "PROBLEMS EXIST PREVENTING THE SAVING OF THE HIGH SCORES.";
  646.     LOCATE 25,1: PRINT "CORRECT PROBLEM AND PRESS 'ENTER' OR PRESS 'A' TO ABORT SAVE. ";
  647.     CALL SCREEN.INPUT((25),(POS(0)),1,"",A$,("A"+CHR$(13))): CALL CLEAR.LINE
  648.     LOCATE 25,1: PRINT SPACE$(79);: LOCATE 25,1
  649.     IF A$="" THEN RESUME PUT.SCORES ELSE RESUME PUTRET
  650. REM *************************************************************************
  651. REM ** DATA STATEMENTS **
  652. BOARD.DATA:
  653.     DATA "╔════╦════╦════╦════╦════╦════╦════╦════╗"
  654.     DATA "║    ║    ║    ║    ║    ║    ║    ║    ║"
  655.     DATA "╠════╬════╬════╬════╬════╬════╬════╬════╣"
  656.     DATA "╚════╩════╩════╩════╩════╩════╩════╩════╝"
  657.     DATA "    ","▐██▌","▐▒▒▌"
  658. COLOR.DATA:
  659.     DATA 7,0,2,0,4,0,6,0,14,4,10,1,0,0
  660. MONO.DATA:
  661.     DATA 7,0,7,0,7,0,7,0,15,7,0,7,0,0
  662. MOVE.DATA:
  663.     DATA -1,-1,0,-1,1,-1,1,0,1,1,0,1,-1,1,-1,0
  664. PATTERN1.DATA:
  665.     DATA 4,3,1,5,3,2,4,4,2,5,4,1
  666. PATTERN2.DATA:
  667.     DATA 4,3,1,5,3,1,4,4,2,5,4,2
  668. COMPUTER.MOVE.DATA:
  669. REM ** SELF DEFENSE **
  670.     DATA 1,1, 8,8, 57,1, 1,8
  671. REM ** TRY TO MOVE TO SIDE & SET TRAPS **
  672.     DATA 1,1, 8,8, 57,1, 1,8
  673. REM ** CHECK FOUR CORNERS **
  674.     DATA 1,8,57,64
  675. REM ** CHECK INNER SQUARE **
  676.     DATA 19,22,43,46
  677.     DATA 20,21,30,38,45,44,35,27
  678. REM ** CHECK OUTER SQUARE **
  679.     DATA 1,1,11,1, 8,8,23,8, 57,1,51,1, 1,8,18,8
  680. REM ** CHECK FOUR CORNERS AND TAKE 10 15 50 55 IF TAKEN **
  681.     DATA 1,10, 8,15, 64,55, 57,50
  682. REM ** CHECK 10 15 50 55 **
  683.     DATA 10,15,55,50
  684. COMPUTER.MOVE.DATA.1:
  685.     DATA 1,2,9,10, 8,7,16,15, 57,49,58,50, 64,56,63,55
  686.     DATA 1,8,57,64
  687. REM *************************************************************************
  688. REM ** START OF SUBPROGRAMS **
  689.     'Prompt screen for input
  690.     ' ROW% = Prompt row, COL% = Prompt column
  691.     ' MAX% = Max # chars to input
  692.     ' CUR$ = Current value of field being prompted, field not altered.
  693.     ' INP$ = Return value
  694.     ' VALID$ = Valid chars during input (see OPT 4)
  695. SUB SCREEN.INPUT(ROW,COL,MAX,CUR$,INP$,VALID$) STATIC
  696. INPSTART:
  697.     CALL MAKE.SOUND((1)): CPS=1: STRFLG=1: INP$=CUR$
  698.     IF LEN(INP$)>MAX THEN INP$=LEFT$(INP$,MAX) ELSE INP$=INP$
  699. INPCLEAR:
  700.     INSFLG=0: SIZ=LEN(INP$): LOCATE ROW,COL,1
  701.     PRINT INP$+STRING$(MAX-SIZ,95);: LOCATE ,COL+CPS-1
  702. INPGET:
  703.     IP$=INKEY$: ON LEN(IP$)+1 GOTO INPGET,INPCHR
  704.     IP=ASC(RIGHT$(IP$,1)): GOTO INPFUN
  705. INPCHR:
  706.     IP=ASC(IP$): IF IP>96 AND IP<123 THEN IP=IP AND 223: IP$=CHR$(IP)
  707.     IF INSTR(VALID$,IP$)=0 THEN GOTO INPCTL
  708. INPDIS:
  709.     IF CPS>MAX THEN GOTO INPERR ELSE CPS=CPS+1
  710.     IF CPS-1>SIZ THEN
  711.         SIZ=SIZ+1: INP$=INP$+IP$: PRINT IP$;
  712.     ELSEIF INSFLG=1 THEN
  713.         SIZ=SIZ+1: INP$=LEFT$(INP$,CPS-2)+IP$+MID$(INP$,CPS-1)
  714.         IF SIZ>MAX THEN INP$=LEFT$(INP$,MAX): SIZ=MAX
  715.         PRINT MID$(INP$,CPS-1);: LOCATE ,COL+CPS-1
  716.     ELSE
  717.         INP$=LEFT$(INP$,CPS-2)+IP$+MID$(INP$,CPS): PRINT IP$;
  718.     END IF
  719.     IF MAX=1 THEN IP=13: GOTO INPFUN
  720.     IF STRFLG THEN STRFLG=0: INP$=IP$: CPS=2: CALL MAKE.SOUND((3)): GOTO INPCLEAR_
  721.     ELSE GOTO INPOK
  722. INPCTL:
  723.     IF IP>=32 THEN GOTO INPERR
  724. INPFUN:
  725.     IF IP<>13 THEN STRFLG=0
  726.     ON INSTR(CHR$(8)+CHR$(13)+CHR$(27)+"GKMORS",CHR$(IP))_
  727.         GOTO INPBS,INPRET,INPSTART,INPBG,INPLC,INPRC,INPED,INPINS,INPDL
  728. INPERR:
  729.     CALL MAKE.SOUND((1)): GOTO INPGET
  730. INPOK:
  731.     CALL MAKE.SOUND((3)): GOTO INPGET
  732. INPBS:
  733.     IF CPS=1 THEN GOTO INPERR ELSE CPS=CPS-1: SIZ=SIZ-1
  734.     IF CPS>SIZ THEN INP$=LEFT$(INP$,SIZ)_
  735.     ELSE INP$=LEFT$(INP$,CPS-1)+MID$(INP$,CPS+1)
  736.     LOCATE ,POS(0)-1: PRINT MID$(INP$,CPS)+STRING$(MAX-SIZ,95);
  737.     LOCATE ,COL+CPS-1: GOTO INPOK
  738. INPBG:
  739.     CPS=1: LOCATE ,COL: GOTO INPOK
  740. INPLC:
  741.     IF CPS>1 THEN CPS=CPS-1: PRINT CHR$(29);: GOTO INPOK ELSE GOTO INPERR
  742. INPRC:
  743.     IF CPS<SIZ+1 THEN CPS=CPS+1: PRINT CHR$(28);: GOTO INPOK ELSE GOTO INPERR
  744. INPED:
  745.     CPS=SIZ+1: LOCATE ,COL+CPS-1: GOTO INPOK
  746. INPINS:
  747.     INSFLG=INSFLG XOR 1: GOTO INPOK
  748. INPDL:
  749.     IF SIZ>=CPS THEN PRINT CHR$(28);: CPS=CPS+1: GOTO INPBS ELSE GOTO INPERR
  750. INPRET:
  751.     IF MAX=1 AND INP$="" AND INSTR(VALID$,CHR$(13))=0 THEN GOTO INPGET
  752.     LOCATE ROW,COL,0: PRINT SPACE$(MAX);: LOCATE ROW,COL
  753. END SUB
  754. SUB MAKE.SOUND(X) STATIC
  755.     SHARED SN$: IF X=8 THEN CALL WAIT.HERE((.2!))
  756.     IF SN$<>"Y" THEN EXIT SUB
  757.     IF X=1 THEN
  758.         PLAY "L64T200N70"
  759.     ELSEIF X=2 THEN
  760.         PLAY "T150MFMLL64O5CC#DD#EFF#GG#AA#B"
  761.     ELSEIF X=3 THEN
  762.         PLAY "L64T200N46"
  763.     ELSEIF X=4 THEN
  764.         BEEP
  765.     ELSEIF X=5 THEN
  766.         PLAY "T200MFL32O5CC#DD#EFF#GG#AA#AG#GF#FED#DC#C"
  767.     ELSEIF X=6 THEN
  768.         PLAY "L64T255N70"
  769.     ELSEIF X=7 THEN
  770.         FOR A=1 TO 7: SOUND 100,1: SOUND 120,1: NEXT
  771.     ELSEIF X=8 THEN
  772.         PLAY "L64T200N60"
  773.     ELSEIF X>=10 THEN
  774.         PLAY "T120L16MFN"+MID$(" 37394142444648495153545658606163656668707273757778808284",(X-9)*2,2)
  775.     END IF
  776. END SUB
  777. SUB DISPLAY.PIECES(X,Y,PLAYER) STATIC
  778.     SHARED BOARD(),TOKEN$(),SCORE(),CLF(),CLB(): A=BOARD(Y*8+X,0)
  779.     IF A<>PLAYER THEN SCORE(PLAYER)=SCORE(PLAYER)+1: BOARD(Y*8+X,0)=PLAYER:_
  780.         IF A<>0 THEN SCORE(PLAYER XOR 3)=SCORE(PLAYER XOR 3)-1
  781.     COLOR CLF(PLAYER),CLB(PLAYER): LOCATE Y*2+2,X*5-3: PRINT TOKEN$(PLAYER);
  782.     COLOR CLF(1),CLB(1): LOCATE 1,46: PRINT USING "##";SCORE(1);: PRINT " -";
  783.     COLOR CLF(2),CLB(2): LOCATE 1,61: PRINT USING "##";SCORE(2);: PRINT " -";
  784.     COLOR 7,0
  785. END SUB
  786. SUB UNDO.MOVE STATIC
  787.     SHARED BOARD(),TOKEN$(),SCORE(),CLF(),CLB(),MOVE.NUM,PLAYERS,CUR.PLYR
  788.     SCORE(0)=0: SCORE(1)=0: SCORE(2)=0: MOVE.NUM=MOVE.NUM-(3-PLAYERS)
  789.     FOR Y=0 TO 7
  790.         FOR X=1 TO 8
  791.             A=Y*8+X: BOARD(A,0)=BOARD(A,MOVE.NUM)
  792.             A=BOARD(A,0): LOCATE Y*2+2,X*5-3
  793.             COLOR CLF(A),CLB(A): PRINT TOKEN$(A);: SCORE(A)=SCORE(A)+1
  794.             IF A THEN CALL MAKE.SOUND((6))
  795.             CALL WAIT.HERE((.05!))
  796.         NEXT
  797.     NEXT
  798.     COLOR CLF(1),CLB(1): LOCATE 1,46: PRINT USING "##";SCORE(1);: PRINT " -";
  799.     COLOR CLF(2),CLB(2): LOCATE 1,61: PRINT USING "##";SCORE(2);: PRINT " -";
  800.     COLOR 7,0: CUR.PLYR=BOARD(0,MOVE.NUM) XOR 3
  801. END SUB
  802. SUB WAIT.HERE(A!) STATIC
  803.     WHILE INKEY$<>"": WEND: B!=TIMER
  804.     WHILE INKEY$="" AND TIMER<(B!+A!): WEND
  805. END SUB
  806. SUB PRINT.MSG(MSG$,COL) STATIC
  807.     SHARED CLF(),CLB()
  808.     VIEW PRINT 25 TO 25: CLS: VIEW PRINT
  809.     COLOR CLF(COL),CLB(COL): LOCATE 25,1: PRINT MSG$;
  810. END SUB
  811. SUB DISPLAY.HELP STATIC
  812.     SHARED BOARD(),TOKEN$(),HELP.FLG: HELP.FLG=HELP.FLG XOR 1
  813.     FOR Y=0 TO 7
  814.         FOR X=1 TO 8
  815.             IF BOARD(Y*8+X,0)<0 THEN LOCATE Y*2+2,X*5-3:_
  816.                 IF HELP.FLG THEN PRINT CHR$(222)+CHR$(28)+CHR$(28)+CHR$(221);_
  817.                 ELSE PRINT " "+CHR$(28)+CHR$(28)+" ";
  818.         NEXT
  819.     NEXT
  820. END SUB
  821. SUB GET.MOVEMENT(DIR) STATIC
  822.     SHARED JS$,JS1,JS2: DIR=0: JSFL1=0: JSFL2=0
  823.     CALL MOUSE((1),(0),(0),(0))
  824.     WHILE DIR=0: A$=INKEY$
  825.         IF A$=CHR$(0)+CHR$(72) THEN DIR=1_
  826.         ELSE IF A$=CHR$(0)+CHR$(77) THEN DIR=3_
  827.         ELSE IF A$=CHR$(0)+CHR$(80) THEN DIR=5_
  828.         ELSE IF A$=CHR$(0)+CHR$(75) THEN DIR=7_
  829.         ELSE IF A$=CHR$(27) THEN DIR=9_
  830.         ELSE IF A$="H" OR A$="h" THEN DIR=10_
  831.         ELSE IF A$="U" OR A$="u" THEN DIR=11_
  832.         ELSE IF A$=" " OR A$=CHR$(13) THEN DIR=8_
  833.         ELSE IF A$<>"" AND DIR=0 THEN CALL MAKE.SOUND((1))
  834.         IF JS$="Y" THEN
  835.             A2=STICK(0): A2=STICK(0): A1=STICK(1)
  836.             IF JSFL1<>0 AND A1>JS1/2 AND A1<JS1+JS1/2 THEN DIR=JSFL1
  837.             IF JSFL2<>0 AND A2>JS2/2 AND A2<JS2+JS2/2 THEN DIR=JSFL2
  838.             IF JSFL1=0 THEN IF A1<JS1/2 THEN JSFL1=1 ELSE IF A1>JS1+JS1/2 THEN JSFL1=5
  839.             IF JSFL2=0 THEN IF A2<JS2/2 THEN JSFL2=7 ELSE IF A2>JS2+JS2/2 THEN JSFL2=3
  840.             IF STRIG(1) THEN WHILE STRIG(1): WEND: CALL WAIT.HERE((.1)): DIR=8
  841.             IF (INP(513) AND 32)=0 THEN WHILE (INP(513) AND 32)=0: WEND: CALL WAIT.HERE((.1)): DIR=10
  842.         END IF
  843.         M1=6: M2=1: CALL MOUSE(M1,M2,(0),(0)): IF (M1 AND 2)=0 AND M2>0 THEN DIR=10
  844.         M1=6: M2=0: CALL MOUSE(M1,M2,M3,M4)
  845.         IF (M1 AND 1)=0 AND M2>0 THEN
  846.             M3=M3/8: M4=M4/8
  847.             IF (M3 MOD 5)<>0 AND (M4 MOD 2)<>0 THEN_
  848.                 M3=INT(M3/5)+1: M4=INT(M4/2): DIR=M3+M4*16+256
  849.         END IF
  850.     WEND: CALL MOUSE((2),(0),(0),(0))
  851. END SUB
  852. SUB MOUSE(M1,M2,M3,M4) STATIC
  853.     SHARED MOUSE.SEG,MOUSE.FLG,MOUSE
  854.     IF M1=-1 THEN
  855.         DEF SEG=0
  856.         MOUSE.SEG=PEEK(207)*256+PEEK(206): MOUSE=PEEK(205)*256+PEEK(204)+2
  857.         DEF SEG=MOUSE.SEG
  858.         IF PEEK(MOUSE-2)=207 OR PEEK(MOUSE-2)=0 THEN_
  859.             DEF SEG: MOUSE=0: MOUSE.SEG=0: MOUSE.FLG=0: GOTO MSRET
  860.         M1=0: CALL ABSOLUTE(M1,M2,M3,M4,MOUSE)
  861.         IF M1=0 THEN DEF SEG: MOUSE=0: MOUSE.SEG=0: MOUSE.FLG=0: GOTO MSRET
  862.         M1=7: M2=0: M3=8: M4=312: CALL ABSOLUTE(M1,M2,M3,M4,MOUSE)
  863.         M1=8: M2=0: M3=8: M4=120: CALL ABSOLUTE(M1,M2,M3,M4,MOUSE)
  864.         DEF SEG: MOUSE.FLG=1
  865.     ELSEIF MOUSE.FLG=1 AND (M1=0 OR M1=1 OR M1=2 OR M1=6 OR M1=10) THEN
  866.         DEF SEG=MOUSE.SEG: CALL ABSOLUTE(M1,M2,M3,M4,MOUSE): DEF SEG
  867.     END IF
  868. MSRET:
  869. END SUB
  870. SUB CLEAR.LINE STATIC
  871.     LOCATE 24,1: PRINT SPACE$(79);: LOCATE 24,1
  872. END SUB
  873.